package com.googlecode.kipler.satisfiability.completion.strategy;

import java.util.ArrayList;
import java.util.List;

import com.googlecode.kipler.container.dl.WorldConstraintSystem;
import com.googlecode.kipler.container.dl.operational.FilterType;
import com.googlecode.kipler.container.dl.operational.RelatedIndividualWithTypeFilter;
import com.googlecode.kipler.container.dl.operational.RelatedIndividualWithTypeFilterFactory;
import com.googlecode.kipler.satisfiability.blocking.abox.ABoxBlockingStrategy;
import com.googlecode.kipler.satisfiability.blocking.abox.OptimizedSHIQABoxBlocking;
import com.googlecode.kipler.satisfiability.completion.rule.individual.ABoxRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AllValuesRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AtLeastRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.AtMostRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.ChooseRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.IntersectionRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.LazyUnfoldingRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.PositiveConceptDefinitionRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SHIQABoxBothRootMergeStrategy;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SHIQABoxNotBothRootMergeStrategy;
import com.googlecode.kipler.satisfiability.completion.rule.individual.SomeValuesRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.TransitivityRule;
import com.googlecode.kipler.satisfiability.completion.rule.individual.UnionRule;
import com.googlecode.kipler.satisfiability.reasoner.Reasoner;
import com.googlecode.kipler.satisfiability.reasoner.ReasonerException;


/**
 * 
 * @author İnanç Seylan
 * 
 */
public class SHIQModifiedIndividualBasedCompletionStrategy implements
		CompletionStrategy {
	private ModifiedIndividualBasedCompletionStrategy strategy = new ModifiedIndividualBasedCompletionStrategy();

	public SHIQModifiedIndividualBasedCompletionStrategy(Reasoner reasoner) {
		setReasoner(reasoner);
		ABoxBlockingStrategy blocking = new OptimizedSHIQABoxBlocking();
		RelatedIndividualWithTypeFilter filterer = RelatedIndividualWithTypeFilterFactory
				.getFilter(FilterType.TYPED_NEIGHBOR);
		List<ABoxRule> ruleList = new ArrayList<ABoxRule>();
		ruleList.add(new LazyUnfoldingRule());
		ruleList.add(new PositiveConceptDefinitionRule(blocking));
		ruleList.add(new IntersectionRule(blocking));
		ruleList.add(new AllValuesRule(blocking));
		ruleList.add(new TransitivityRule(blocking));
		ruleList.add(new UnionRule(getReasoner(), blocking));
		ruleList.add(new ChooseRule(getReasoner(), blocking));
		ruleList.add(new AtMostRule(getReasoner(), blocking,
				new SHIQABoxBothRootMergeStrategy()));
		ruleList.add(new AtMostRule(getReasoner(), blocking,
				new SHIQABoxNotBothRootMergeStrategy()));
		ruleList.add(new SomeValuesRule(blocking, filterer, false));
		ruleList.add(new AtLeastRule(blocking, filterer, false));
		strategy.setRuleList(ruleList);
	}

	@Override
	public void apply(WorldConstraintSystem currentWcs)
			throws ReasonerException {
		strategy.apply(currentWcs);
	}

	@Override
	public Reasoner getReasoner() {
		return strategy.getReasoner();
	}

	@Override
	public void setReasoner(Reasoner reasoner) {
		strategy.setReasoner(reasoner);
	}

	// private List<ABoxRule> generatingRuleList = new ArrayList<ABoxRule>();
	//
	// private List<ABoxRule> shrinkingRuleList = new ArrayList<ABoxRule>();
	//
	// private List<ABoxRule> labelModifyingRuleList = new
	// ArrayList<ABoxRule>();
	//
	// private Reasoner reasoner;
	//
	// private World currentWorld;
	//
	// private WorldConstraintSystem currentWcs;
	//
	// public SHIQModifiedIndividualBasedCompletionStrategy(Reasoner reasoner) {
	// setReasoner(reasoner);
	// BlockingStrategy blocking = new OptimizedSHIQABoxBlocking();
	// RelatedIndividualWithTypeFilter filterer =
	// RelatedIndividualWithTypeFilterFactory
	// .getFilter(FilterType.TYPED_NEIGHBOR);
	// labelModifyingRuleList.add(new LazyUnfoldingRule());
	// labelModifyingRuleList.add(new PositiveConceptDefinitionRule(blocking));
	// labelModifyingRuleList.add(new IntersectionRule(blocking));
	// labelModifyingRuleList.add(new AllValuesRule(blocking));
	// labelModifyingRuleList.add(new TransitivityRule(blocking));
	// labelModifyingRuleList.add(new UnionRule(getReasoner(), blocking));
	// labelModifyingRuleList.add(new ChooseRule(getReasoner(), blocking));
	//
	// shrinkingRuleList.add(new AtMostRule(getReasoner(), blocking,
	// new SHIQABoxBothRootMergeStrategy()));
	// shrinkingRuleList.add(new AtMostRule(getReasoner(), blocking,
	// new SHIQABoxNotBothRootMergeStrategy()));
	//
	// generatingRuleList.add(new SomeValuesRule(blocking, filterer, false));
	// generatingRuleList.add(new AtLeastRule(blocking, filterer, false));
	// }
	//
	// /**
	// * @return the reasoner
	// */
	// public Reasoner getReasoner() {
	// return reasoner;
	// }
	//
	// /**
	// * @param reasoner
	// * the reasoner to set
	// */
	// public void setReasoner(Reasoner reasoner) {
	// this.reasoner = reasoner;
	// }
	//
	// public void apply(WorldConstraintSystem currentWcs)
	// throws ReasonerException {
	// currentWorld = currentWcs.getAllWorlds().iterator().next();
	// this.currentWcs = currentWcs;
	// CompletionRule compRule = new NegatedRoleInclusionRule(currentWcs,
	// currentWorld);
	// compRule.apply();
	// compRule = new NegatedConceptDefinitionRule(currentWcs, currentWorld);
	// compRule.apply();
	// compRule = new EmptyDomainRule(currentWcs, currentWorld);
	// compRule.apply();
	// do {
	// applyLabelModifyingRules();
	// } while (applyShrinkingRules() || applyGeneratingRules());
	// }
	//
	// private void applyLabelModifyingRules() throws ReasonerException {
	// boolean ruleApplied;
	// do {
	// ruleApplied = false;
	// Set<String> iterationCopy = new HashSet<String>(getModIndvList()
	// .get(currentWorld.getName()));
	// for (String indvName : iterationCopy) {
	// Individual indv = currentWorld.getABox()
	// .getIndividual(indvName);
	// while (new RuleApplication(currentWcs, currentWorld)
	// .applySingleIndividualRule(labelModifyingRuleList, indv)) {
	// ruleApplied = true;
	// }
	// }
	// } while (ruleApplied);
	// }
	//
	// private boolean applyShrinkingRules() throws ReasonerException {
	// return applyARuleFromRuleList(shrinkingRuleList, false);
	// }
	//
	// private boolean applyGeneratingRules() throws ReasonerException {
	// return applyARuleFromRuleList(generatingRuleList, true);
	// }
	//
	// private boolean applyARuleFromRuleList(List<ABoxRule> ruleList,
	// boolean removeIfNonApplicable) throws ReasonerException {
	// boolean ruleApplied = false;
	// Set<String> removeSet = new HashSet<String>();
	// Iterator<String> i = getModIndvList().get(currentWorld.getName())
	// .iterator();
	// while (i.hasNext() && !ruleApplied) {
	// String indvName = i.next();
	// Individual indv = currentWorld.getABox().getIndividual(indvName);
	// ruleApplied = new RuleApplication(currentWcs, currentWorld)
	// .applySingleIndividualRule(ruleList, indv);
	// if (!ruleApplied && removeIfNonApplicable) {
	// removeSet.add(indvName);
	// }
	// }
	// for (String indvName : removeSet) {
	// getModIndvList().remove(currentWorld.getName(), indvName);
	// }
	// return ruleApplied;
	// }
	//
	// private ModifiedIndividualCollection getModIndvList() {
	// return currentWcs.getData().getModifiedIndividuals();
	// }
}
